﻿//*** Guidance generated code ***//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Mvc;

using ProjectBase.Core;
using ProjectBase.Core.Web;

namespace $safeprojectname$
{
    public abstract class SelectOptionControl<TSourceProperty, TPropertyControl> : DetailLinkControl<TSourceProperty, TPropertyControl>
        where TPropertyControl : SelectOptionControl<TSourceProperty, TPropertyControl>
    {
        #region members
        IComboBoxModel _comboBoxModel;
        string _dataTextField = Constants.Common.Display;
        string _dataValueField = Constants.Common.ID;
        bool? _hasEmpty;
        #endregion members

        #region constructor
        public SelectOptionControl(bool? asReadonly = null) : base(asReadonly) { }
        #endregion constructor

        #region Set public
        public virtual TPropertyControl SetComboBoxModel(IComboBoxModel comboBoxModel)
        {
            ComboBoxModel = comboBoxModel;
            return this as TPropertyControl;
        }

        /// <summary>
        ///     Dynamically sets the SelectList collection.
        ///     If SelectList is set, other properties are not used:
        ///     Items, SelectedValue, DataValueKey, DataTextKey
        /// </summary>
        /// <param name = "selectList"></param>
        /// <returns></returns>
        public virtual TPropertyControl SetSelectList(SelectList selectList)
        {
            Contract.Requires(selectList.Is(), " SelectList 'selectList' must be set to an instance ");
            Items = selectList.Items;
            DataTextField = selectList.DataTextField;
            DataValueField = selectList.DataValueField;
            SelectedValue = new[] { selectList.SelectedValue.ToString() };
            return this as TPropertyControl;
        }

        /// <summary>
        ///     Dynamically sets items collection for SelectList.
        ///     (e.g. the CodeList entities list)
        ///     Also properties DataValueKey, DataTextKey must be provided
        /// </summary>
        /// <param name = "items"></param>
        /// <returns></returns>
        public virtual TPropertyControl SetDataSource(IEnumerable items)
        {
            Items = items;
            return this as TPropertyControl;
        }

        /// <summary>
        ///     Object representing selected value.
        ///     The best way is to provide string value of the key ...
        /// </summary>
        /// <param name = "selectedValue"></param>
        /// <returns></returns>
        public virtual TPropertyControl SetSelectedValue(string selectedValue)
        {
            SelectedValue = new[] { selectedValue };
            if (selectedValue.Is())
            {
                Text = selectedValue + " ";
            }
            return this as TPropertyControl;
        }

        /// <summary>
        ///     The name of the property which holds the description
        /// </summary>
        /// <param name = "dataTextField"></param>
        /// <returns></returns>
        public virtual TPropertyControl SetDataTextField(string dataTextField)
        {
            Contract.Requires(dataTextField.IsNotEmpty(),
                " dataTextField cannot be null nor empty. It defines the Text property");
            _dataTextField = dataTextField;
            return this as TPropertyControl;
        }

        /// <summary>
        ///     The name of the property which holds the value
        /// </summary>
        /// <param name = "dataValueField"></param>
        /// <returns></returns>
        public virtual TPropertyControl SetDataValueField(string dataValueField)
        {
            Contract.Requires(dataValueField.IsNotEmpty(),
                " dataValueField cannot be null nor empty. It defines the Value property");
            _dataValueField = dataValueField;
            return this as TPropertyControl;
        }

        /// <summary>
        ///     Should be the empty option displayed?
        /// </summary>
        /// <param name = "showEmpty"></param>
        /// <returns></returns>
        public virtual TPropertyControl ShowEmpty(bool showEmpty)
        {
            HasEmpty = showEmpty;
            return this as TPropertyControl;
        }
        #endregion Set public

        #region properties
        public override string InputName
        {
            get
            {
                if (ComboBoxModel.Is()
                    && ComboBoxModel.ComboBoxName.IsNotEmpty())
                {
                    return ComboBoxModel.ComboBoxName;
                }
                return base.InputName;
            }
            set { base.InputName = value; }
        }

        /// <summary>
        ///     The ViewDataModel shoud be the IComboboxModel
        /// </summary>
        public virtual IComboBoxModel ComboBoxModel
        {
            get
            {
                if (_comboBoxModel.IsNull())
                {
                    return Model as IComboBoxModel;
                }
                return _comboBoxModel;
            }
            set { _comboBoxModel = value; }
        }

        protected virtual IEnumerable<SelectListItem> Data
        {
            get
            {
                var list = new List<SelectListItem>();
                if (ComboBoxModel.Is()
                    && ComboBoxModel.Items.IsNotEmpty())
                {
                    list.AddRange(ComboBoxModel.Items);
                }
                else if (Items.Is())
                {
                    list.AddRange(new MultiSelectList(Items, DataValueField, DataTextField, SelectedValue));
                }
                if (HasEmpty)
                {
                    list.Insert(0, new SelectListItem { Value = string.Empty, Text = NotFoundOrNullTemplate });
                }
                return list;
            }
        }

        /// <summary>
        ///     The collection of source value for Option elements
        /// </summary>
        public virtual IEnumerable Items { get; set; }

        /// <summary>
        ///     Will be the first option empty row, allowing neutral value?
        /// </summary>
        public virtual bool HasEmpty
        {
            get
            {
                if (_hasEmpty.IsNull())
                {
                    if (ComboBoxModel.Is())
                    {
                        _hasEmpty = ComboBoxModel.ShowEmpty;
                    }
                }
                return _hasEmpty ?? false;
            }
            set { _hasEmpty = value; }
        }

        public override bool ShowReadOnly
        {
            get
            {
                if ((!(Model is IViewModel))
                    && ComboBoxModel.Is())
                {
                    return false;
                }
                return base.ShowReadOnly;
            }
            set { base.ShowReadOnly = value; }
        }

        /// <summary>
        ///     The object representing selected value
        /// </summary>
        public virtual IEnumerable SelectedValue { get; set; }

        /// <summary>
        ///     The property name, which holds the key.
        ///     Default value is Constants.Common.ID = "ID"
        /// </summary>
        public virtual string DataValueField
        {
            get { return _dataValueField; }
            set
            {
                Contract.Requires(value.IsNotEmpty(), " DataValueField cannot be null nor empty");
                _dataValueField = value;
            }
        }

        /// <summary>
        ///     The property name, which contains description.
        ///     Default value is Constants.Common.Display = "Display";
        /// </summary>
        public virtual string DataTextField
        {
            get { return _dataTextField; }
            set
            {
                Contract.Requires(value.IsNotEmpty(), " DataTextField cannot be null nor empty");
                _dataTextField = value;
            }
        }
        #endregion properties
    }
}